﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;

namespace Common.XmlHandle
{
    public class XmlUsersData
    {
        private XmlDocument xdoc;
        private XmlNode root;
        private string xmlPath;

        public XmlUsersData(string path)
        {
            xmlPath = path;
            try
            {
                xdoc = new XmlDocument();
                xdoc.Load(path);
                root = xdoc.SelectSingleNode("Users");
            }
            catch (DirectoryNotFoundException)
            {
                Directory.CreateDirectory(path.Substring(0, path.LastIndexOf(@"\")));
            }
            catch (FileNotFoundException)
            {
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement("Users"));
                xdoc.Save(path);
            }
            catch (XmlException)
            {
                xdoc = new XmlDocument();
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement("Users"));
                xdoc.Save(path);
            }
            catch
            {
                throw;
            }
        }

        public ClassConfig GetUser(string username)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            XmlNode node = QueryUser(username);
            if(node != null)
            {
                return GetConfigByNode(node);
            }
            else
            {
                throw new Exception("用户 " + username + " 不存在");
                //ClassConfig config = new ClassConfig();
                //config.ToDefault();
                //config.UserGuid = Guid.NewGuid();
                //config.UserName = username;
                //return config;
            }
        }

        public List<ClassConfig> GetUsersOn()
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            List<ClassConfig> b = new List<ClassConfig>(10);
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                if (Boolean.Parse(node.Attributes["State"].InnerText))
                {
                    b.Add(GetConfigByNode(node));
                }
            }
            return b;
        }

        public List<ClassConfig> GetAllUsers()
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            List<ClassConfig> b = new List<ClassConfig>(10);
            XmlNodeList nodes = root.ChildNodes;
            foreach (XmlNode node in nodes)
            {
                b.Add(GetConfigByNode(node));
            }
            return b;
        }

        public bool IsDefindUser(string username)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            if (QueryUser(username) == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private XmlNode QueryUser(string username)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                XmlElement nod = (XmlElement)node;
                XmlNodeList nos = nod.ChildNodes;
                XmlElement ele = (XmlElement)nos[0];
                if (ele.InnerText.Equals(username))
                {
                    return node;
                }
            }
            return null;
        }

        public void Change2Away(Guid guid)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                XmlElement nod = (XmlElement)node;
                if (nod.GetAttribute("Guid").Equals(guid))
                {
                    nod.Attributes["State"].InnerText = "False";
                }
            }
        }

        public void AddUser(ClassConfig config)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            XmlNode query = QueryUser(config.UserName);
            if (query == null)
            {
                AddNode(config);
            }
            else
            {
                EditNode(query, config);
            }
            this.xdoc.Save(this.xmlPath);
        }

        public void EditUser(ClassConfig config)
        {
            xdoc.Load(xmlPath);
            root = xdoc.SelectSingleNode("Users");
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                XmlElement nod = (XmlElement)node;
                if (nod.GetAttribute("Guid").Equals(config.UserGuid.ToString()))
                {
                    EditNode(node, config);
                }
            }
            this.xdoc.Save(this.xmlPath);
        }

        private ClassConfig GetConfigByNode(XmlNode node)
        {
            if (node != null)
            {
                ClassConfig config = new ClassConfig();
                XmlElement nod = (XmlElement)node;
                config.UserGuid = new Guid(nod.GetAttribute("Guid"));
                config.State = Boolean.Parse(nod.GetAttribute("State"));
                XmlNodeList nodeList = node.ChildNodes;
                config.UserName = nodeList[0].InnerText;
                config.UserLicense = (License)Enum.Parse(typeof(License), nodeList[1].InnerText);
                config.IsServer = Convert.ToBoolean(nodeList[2].InnerText);
                config.IsAdmin = Convert.ToBoolean(nodeList[3].InnerText);
                config.IsCustomize = Convert.ToBoolean(nodeList[4].InnerText);
                config.IsQueryOnly = Convert.ToBoolean(nodeList[5].InnerText);
                config.InPath = nodeList[6].InnerText;
                config.OutPathFromString(nodeList[7].InnerText);
                return config;
            }
            else
            {
                return null;
            }
        }

        private void AddNode(ClassConfig config)
        {
            XmlElement node = xdoc.CreateElement("User");
            node.SetAttribute("Guid", config.UserGuid.ToString());
            node.SetAttribute("State", config.State.ToString());
            root.AppendChild(node);
            XmlElement ele = xdoc.CreateElement("UserName");
            ele.InnerText = config.UserName;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("UserLicence");
            ele.InnerText = config.UserLicense.ToString();
            node.AppendChild(ele);
            ele = xdoc.CreateElement("IsServer");
            ele.InnerText = config.IsServer.ToString();
            node.AppendChild(ele);
            ele = xdoc.CreateElement("IsAdmin");
            ele.InnerText = config.IsAdmin.ToString();
            node.AppendChild(ele);
            ele = xdoc.CreateElement("IsCustomize");
            ele.InnerText = config.IsCustomize.ToString();
            node.AppendChild(ele);
            ele = xdoc.CreateElement("IsQueryOnly");
            ele.InnerText = config.IsQueryOnly.ToString();
            node.AppendChild(ele);
            ele = xdoc.CreateElement("InPath");
            ele.InnerText = config.InPath;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("OutPath");
            ele.InnerText = config.OutPath2String();
            node.AppendChild(ele);
            xdoc.Save(this.xmlPath);
        }

        private void EditNode(XmlNode node, ClassConfig config)
        {
            if(node == null | config == null)
            {
                return;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("         " + node.Attributes[0].InnerText.ToString());
                if (node.Attributes[0].InnerText.Equals(config.UserGuid.ToString()))
                {
                    node.Attributes[1].InnerText = config.State.ToString();
                    XmlNodeList nodes = node.ChildNodes;
                    nodes[0].InnerText = config.UserName;
                    nodes[1].InnerText = config.UserLicense.ToString();
                    nodes[2].InnerText = config.IsServer.ToString();
                    nodes[3].InnerText = config.IsAdmin.ToString();
                    nodes[4].InnerText = config.IsCustomize.ToString();
                    nodes[5].InnerText = config.IsQueryOnly.ToString();
                    nodes[6].InnerText = config.InPath;
                    nodes[7].InnerText = config.OutPath2String();
                    xdoc.Save(this.xmlPath);
                }
                else
                {
                    return;
                }
            }
        }
    }
}
